/**
 * @name TodoList
 * @author darcrand
 * @desc 每个成员单独的todos
 */

import React, { Component, useMemo } from 'react'
import { Button, Form, Input, Avatar, Drawer, Divider, message, Radio } from 'antd'
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'
import moment from 'moment'
import BraftEditor from 'braft-editor'
import MaxLength from 'braft-extensions/dist/max-length'
import 'braft-editor/dist/index.css'

import { apiAddTodo, apiGetTodos, apiUpdateTodo, apiRemoveTodo } from '@/apis/todo'
import styles from './styles.module.less'

// 填写富文本最大字数限制
BraftEditor.use(MaxLength())

const defaultProxy = process.env.REACT_APP_DEFAULT_PROXY
// 刷新非当前用户的列表
const REFRESH_DELAY = 10 * 1000
// 最大文章内容长度
const MAX_CONTENT_LENGTH = 500

// 完成状态选项,因为只有两个,就先写死
const statusOptions = [
  { value: 'doing', label: 'Doing' },
  { value: 'done', label: 'Done' },
]

class TodoList extends Component {
  static defaultProps = {
    projectId: '',
    user: {
      isCurrUser: false,
    },
  }

  state = {
    list: [],

    // 如果是当前用户,即可编辑
    visibleEditing: false,
    editingTodo: {
      _id: '',
      title: '',
      content: '',
      status: statusOptions[0].value,
    },
  }

  refreshTimer = null

  componentDidMount() {
    this.getTodos()
    if (!this.props.user.isCurrUser) {
      this.initRefresh()
    }
  }

  componentWillUnmount() {
    this.refreshTimer && clearInterval(this.refreshTimer)
    this.setState = () => {}
  }

  getTodos = async () => {
    const { projectId, user } = this.props
    try {
      const list = await apiGetTodos(
        { pid: projectId, uid: user._id },
        { useLoading: user.isCurrUser, useError: user.isCurrUser }
      )
      this.setState({ list: list.map(v => ({ ...v, date: moment(v.updatedAt).calendar() })) })
    } catch (err) {}
  }

  // 非当前用户目前需要轮询列表内容
  initRefresh = () => {
    this.refreshTimer = setInterval(this.getTodos, REFRESH_DELAY)
  }

  onOpenEditor = (todo = null) => {
    const { editingTodo } = this.state
    this.setState({ visibleEditing: true, editingTodo: todo || editingTodo })
  }

  // 关闭,重置数据
  onCloseEditor = () => {
    this.setState({
      visibleEditing: false,
      editingTodo: { _id: '', title: '', content: '', status: statusOptions[0].value },
    })
  }

  // 更新/新增
  onUpdateTodo = async (values = {}) => {
    const { projectId } = this.props
    const isCreate = !Boolean(this.state.editingTodo._id)

    try {
      if (isCreate) {
        await apiAddTodo({ pid: projectId, ...values })
      } else {
        await apiUpdateTodo(this.state.editingTodo._id, { pid: projectId, ...values })
      }
      this.onCloseEditor()
      this.getTodos()
    } catch (err) {}
  }

  onRemoveTodo = async id => {
    try {
      await apiRemoveTodo(id)
      this.getTodos()
    } catch (err) {}
  }

  render() {
    const { user } = this.props
    const { list, visibleEditing, editingTodo } = this.state

    return (
      <>
        <div className={styles.container}>
          <section className={styles.user_wrapper}>
            <Avatar src={defaultProxy + user.avatar} />
            <p className={styles.name}>{user.nickname}</p>
          </section>

          <ol className={styles.list}>
            {user.isCurrUser && (
              <li className={styles.item_add} onClick={() => this.onOpenEditor()}>
                <PlusOutlined />
              </li>
            )}

            {list.map(t => (
              <Item
                key={t._id}
                data={t}
                isCurrUser={user.isCurrUser}
                onOpenEditor={this.onOpenEditor}
                onRemoveTodo={this.onRemoveTodo}
              />
            ))}
          </ol>

          {!user.isCurrUser && list.length === 0 && <Divider>No Data</Divider>}
        </div>

        {user.isCurrUser && (
          <TodoEditor
            visible={visibleEditing}
            data={editingTodo}
            onCancel={this.onCloseEditor}
            onSubmit={this.onUpdateTodo}
          />
        )}
      </>
    )
  }
}

const Item = ({ data = {}, isCurrUser = false, onOpenEditor = () => {}, onRemoveTodo = () => {} }) => {
  const { _id, date, title, content, status } = data
  const computedClassName = useMemo(() => {
    const arr = [styles.item]
    arr.push(status === 'done' ? styles.item_done : styles.item_doing)
    return arr.join(' ')
  }, [status])

  return (
    <li className={computedClassName}>
      <section className={styles.header}>
        <div className={styles.date}>{date}</div>
        {isCurrUser && (
          <div className={styles.ctrs}>
            <EditOutlined className={styles.btn} title='Edit' onClick={() => onOpenEditor(data)} />
            <DeleteOutlined className={styles.btn} title='Delete' onClick={() => onRemoveTodo(_id)} />
          </div>
        )}
      </section>

      <h3 className={styles.title}>{title}</h3>
      <section className={styles.html_content} dangerouslySetInnerHTML={{ __html: content }} />
    </li>
  )
}

class TodoEditor extends Component {
  static defaultProps = {
    visible: false,
    data: {
      _id: '',
      title: '',
      content: '',
    },
    onSubmit: values => {},
    onCancel: () => {},
  }

  // 由于提供api无法自适应宽度,自己计算
  state = { contentWidht: 700 }

  refForm = React.createRef()

  componentDidMount() {
    const windowWidth = window.document.documentElement.clientWidth
    const { contentWidht } = this.state
    if (windowWidth < contentWidht) {
      this.setState({ contentWidht: windowWidth })
    }
  }

  componentDidUpdate(prevProps) {
    if (!prevProps.visible && this.props.visible) {
      const timeout = this.refForm.current ? 0 : 500
      const { title, content, status } = this.props.data
      setTimeout(() => {
        if (this.refForm.current) {
          this.refForm.current.setFieldsValue({
            title: title,
            editorState: BraftEditor.createEditorState(content || ''),
            status,
          })
        }
      }, timeout)
    }
  }

  onFieldsChange = obj => {
    if (obj && obj.type) {
      this.setState({ title: obj.target.value })
    } else {
      this.setState({ editorState: obj })
    }
  }

  onTiggerSubmit = () => {
    this.refForm.current && this.refForm.current.submit()
  }

  onSubmit = (values = {}) => {
    const { title, editorState, status } = values
    const content = editorState.toHTML()

    this.props.onSubmit && this.props.onSubmit({ title, content, status })
  }

  render() {
    const { visible, onCancel, data } = this.props
    const { contentWidht } = this.state

    return (
      <Drawer
        visible={visible}
        maskClosable={false}
        title={data._id ? 'Update' : 'Create'}
        width={contentWidht}
        onClose={onCancel}
        footer={
          <div>
            <Button onClick={onCancel} style={{ marginRight: 8 }}>
              Cancel
            </Button>
            <Button onClick={this.onTiggerSubmit} type='primary'>
              Submit
            </Button>
          </div>
        }
      >
        <Form ref={this.refForm} layout='vertical' onFinish={this.onSubmit}>
          <Form.Item label='Title' name='title' rules={[{ required: true, message: 'Please input a title!' }]}>
            <Input />
          </Form.Item>
          <Form.Item label='Status' name='status'>
            <Radio.Group options={statusOptions} />
          </Form.Item>
          <Form.Item label='Content' name='editorState'>
            <BraftEditor
              language='en'
              excludeControls={['media']}
              maxLength={MAX_CONTENT_LENGTH}
              onReachMaxLength={() => message.warn("You can't enter it anymore!")}
            />
          </Form.Item>
        </Form>
      </Drawer>
    )
  }
}

export default TodoList
